Матч 226, Движение по Манхетену (ManhattanMovement)

Дивизион 2, Уровень 3; Дивизион 1, Уровень 1

 

Вы находитесь в городе в точке (x0, y0) и вам разрешено двигаться в любом из четырех направлений параллельно осям координат. В любой точке пути можно изменять направление движения на одно из четырех допустимых. В городе имеется дорога в виде бесконечной прямой, уравнение которой имеет вид: ax + by = 1. Вам необходимо выйти на эту дорогу по кратчайшему пути.

 

Класс: ManhattanMovement

Метод: double getDistance(int a, int b, int x0, int y0)

Ограничения: a и b одновременно не равны нулю.

 

Вход. Целые чсла a, b, x0, y0.

 

Выход. Длина кратчайшего пути, которым можно выйти из точки (x0, y0) на дорогу, заданную уравнением ax + by = 1.

 

Пример входа

a

b

x0

y0

1

2

-2

3

37

37

42

19

-100

0

-999999

314159

 

Пример выхода

1.5

60.97297297297297

999998.99

 

 

РЕШЕНИЕ

геометрия

 

Для решения задачи следует заметить, что для выхода на дорогу достаточно выбрать правильное направление и идти нигде не сворачивая. Если прямая ax + by = 1 имеет горизонтальный или вертикальнаый вид, то достаточно выбрать направление непосредственно к ней, которое будет допустимым. Если прямая не параллельна ни одной из осей координат, то достаточно вычислить расстояние до нее в горизонтальном и вертикальном направлениях и найти среди них наименьшее.

 

ПРОГРАММА

 

#include <stdio.h>

#include <math.h>

 

class ManhattanMovement

{

public:

  double getDistance(int a, int b, int x0, int y0)

  {

    double t1, t2;

    if (!a) return fabs(1.0 / b - y0);

    if (!b) return fabs(1.0 / a - x0);

    t1 = fabs((1 - (double)a * x0) / b - y0);

    t2 = fabs((1 - (double)b * y0) / a - x0);

    return (t1 < t2) ? t1 : t2;

  }

};